package train_service

import (
	"encoding/json"
	"fmt"
	"os"
	"peilian-api/app/global/common"
	"peilian-api/app/global/databases/tables"
	"peilian-api/app/global/log"
	"peilian-api/app/global/variable"
	"peilian-api/app/model"
	"peilian-api/utils/sdk"
	"peilian-api/utils/tools"
	"time"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

// 导出学生面试记录
func ExportTrainLog(ctx *gin.Context, queryReq model.ExportTrainLog) (out []interface{}, count int64, url string, err error) {
	var ss []tables.Session
	var whereMap map[string]interface{} = make(map[string]interface{})
	// 获取学校的信息
	uid, exists := ctx.Get("uid")
	if !exists {
		return out, 0, "", fmt.Errorf("操作失败~")
	}
	us, _ := tables.GetAgentInfoByUid(uid.(uint))
	level := us.Level
	consId := us.ConstituteID

	// 参数
	query := queryReq.Query
	schoolId := queryReq.School
	academy := queryReq.Academy
	profession := queryReq.Profession
	grade := queryReq.Grade
	education := queryReq.Education
	startTime := queryReq.StartTime
	endTime := queryReq.EndTime

	where := fmt.Sprintf("status = 1 and train_at >= '%s' and train_at <= '%s'", startTime, endTime)
	if us.Type == tables.UserTypeSadmin {
		if schoolId != 0 {
			ci, _ := new(tables.Constitute).GetConstituteById(schoolId)
			whereMap["school"] = ci.Name
		}
	} else {
		whereMap["school"] = us.School
	}
	if len(education) != 0 {
		whereMap["education"] = education
	}
	if level == tables.RolesLevel3 {
		ci, _ := new(tables.Constitute).GetupConfigMap(consId)
		whereMap["academy"] = ci[tables.AcademyType].Name
		if profession != 0 {
			ci, _ := new(tables.Constitute).GetConstituteById(profession)
			whereMap["profession"] = ci.Name
		}
	} else if level == tables.RolesLevel4 {
		ci, _ := new(tables.Constitute).GetupConfigMap(consId)
		whereMap["academy"] = ci[tables.AcademyType].Name
		whereMap["profession"] = ci[tables.ProfessionType].Name
	} else {
		if academy != 0 {
			ci, _ := new(tables.Constitute).GetConstituteById(academy)
			whereMap["academy"] = ci.Name
		}
		if profession != 0 {
			ci, _ := new(tables.Constitute).GetConstituteById(profession)
			whereMap["profession"] = ci.Name
		}
	}

	if len(grade) != 0 && grade != "全部年级" && grade != "0" {
		whereMap["grade"] = grade
	}

	if len(query) != 0 { // 默认使用用户名查询
		query = "%" + query + "%" // 模糊查询
		d := variable.DB.MySQL.Where(whereMap).Where(where).Where("user_phone like ? or user_name like ? or sno like ?", query, query, query).Order("created_at desc").Preload("Career").Find(&ss)
		if d.RowsAffected == 0 {
			return out, 0, "", nil
		}
	} else {
		d := variable.DB.MySQL.Where(whereMap).Where(where).Order("created_at desc").Preload("Career").Find(&ss)
		if d.RowsAffected == 0 {
			return out, 0, "", nil
		}
	}

	var phontUri = variable.Config.UfsInfo.UfsUrl + variable.Config.UfsInfo.BucketPrefix
	for i := 0; i < len(ss); i++ {
		var trainLog model.QueryTrainLogResp
		trainLog.Id = ss[i].ID
		trainLog.Career = ss[i].CareerName
		trainLog.Academy = ss[i].Academy
		trainLog.Grade = ss[i].Grade
		trainLog.Name = ss[i].UserName
		trainLog.Phone = ss[i].UserPhone
		trainLog.Profession = ss[i].Profession
		trainLog.School = ss[i].School
		trainLog.TrainTime = ss[i].TrainAt.Format("2006-01-02 15:04:05")
		trainLog.ReportUrl = phontUri + ss[i].Url
		if ss[i].Career != nil {
			trainLog.ReportType = ss[i].Career.ReportType
		}
		if ss[i].Career.ReportType == "web" {
			trainLog.ReportUrl = fmt.Sprintf(
				"https://growup.aminer.cn/%s/web-report?reportId=%d&careerId=%d",
				variable.Env, ss[i].ID, ss[i].CareerID,
			)
		}
		trainLog.Score = int((ss[i].TotalScore))
		trainLog.FinishTime = ss[i].FinishAt.Format("2006-01-02 15:04:05")
		trainLog.Status = ss[i].Status
		trainLog.Duration = fmt.Sprintf("%d分%d秒", ss[i].Duration/60, ss[i].Duration%60)
		trainLog.Education = ss[i].Education
		trainLog.Type = tables.UseTypeMap[ss[i].Type]
		trainLog.Sno = ss[i].Sno
		trainLog.ReportIsSync = ss[i].IsSync
		u := new(tables.User)
		d := variable.DB.MySQL.First(u, ss[i].UserID)
		if d.Error == gorm.ErrRecordNotFound {
			continue
		}
		if !u.IsSync {
			trainLog.ReportIsSync = false
		}
		agent := new(tables.Agent)
		agentSubquery := variable.DB.MySQL.Model(&tables.User{}).Select("agent_id").Where("id=?", ss[i].UserID)
		if err := variable.DB.MySQL.Select("IsSync").Where("id in (?)", agentSubquery).First(agent); err != nil {
			trainLog.AgentIsSync = true
		}
		trainLog.AgentIsSync = agent.IsSync
		out = append(out, trainLog)
	}
	dir, _ := os.Getwd()
	fileName := tools.Md5DataString(time.Now().String()) + ".xlsx"
	localPath := dir + "/logs/" + fileName
	if _, err := tools.SaveExcle(localPath, "sheet1", common.TrainLogDetailHeader, out); err != nil {
		log.Logger.InfoF(ctx, "文件保存失败"+fileName)
		// 记录日志
		go func() {
			defer tools.RecoverGoroutine()
			new(tables.OptionLog).InsertOptionLog(ctx, int64(len(out)), err)
		}()
		return out, count, "", fmt.Errorf("文件导出失败，请重试")
	} else {
		filePath := common.ExportFilePath + fileName
		sdk.FilePut(localPath, variable.Config.UfsInfo.BucketPrefix+filePath, sdk.XlsxMetaType)
		os.Remove(fileName)
		// 记录日志
		go func() {
			defer tools.RecoverGoroutine()
			new(tables.OptionLog).InsertOptionLog(ctx, int64(len(out)), err)
		}()
		return out, count, variable.Config.UfsInfo.UfsUrl + variable.Config.UfsInfo.BucketPrefix + filePath, nil
	}

}

// 获取用户记录
func QueryTrainLog(ctx *gin.Context, queryReq model.QueryTrainLogReq, typ int) (out []interface{}, count int64, url string, err error) {
	var ss []tables.Session
	var whereMap map[string]interface{} = make(map[string]interface{})

	// 获取学校的信息
	uid, exists := ctx.Get("uid")
	if !exists {
		return out, 0, "", fmt.Errorf("操作失败~")
	}
	us, _ := tables.GetAgentInfoByUid(uid.(uint))
	level := us.Level
	consId := us.ConstituteID

	// 参数
	page := queryReq.Page
	pageSize := queryReq.PageSize
	query := queryReq.Query
	career := queryReq.Career
	schoolId := queryReq.School
	academy := queryReq.Academy
	profession := queryReq.Profession
	grade := queryReq.Grade
	startTime := queryReq.StartTime
	endTime := queryReq.EndTime
	education := queryReq.Education
	opt := queryReq.Opt
	userType := queryReq.Type

	where := fmt.Sprintf("status = 1 and created_at >= '%s' and created_at <= '%s'", startTime, endTime)
	if us.Type == tables.UserTypeSadmin {
		if schoolId != 0 {
			ci, _ := new(tables.Constitute).GetConstituteById(schoolId)
			whereMap["school"] = ci.Name
		}
	} else {
		whereMap["school"] = us.School
	}
	if len(userType) != 0 && userType != "0" {
		whereMap["type"] = tables.StafMapArr[userType]
	}
	if career != 0 {
		whereMap["career_id"] = career
	}
	if len(education) != 0 {
		whereMap["education"] = education
	}

	if level == tables.RolesLevel3 {
		ci, _ := new(tables.Constitute).GetupConfigMap(consId)
		whereMap["academy"] = ci[tables.AcademyType].Name
		if profession != 0 {
			ci, _ := new(tables.Constitute).GetConstituteById(profession)
			whereMap["profession"] = ci.Name
		}
	} else if level == tables.RolesLevel4 {
		ci, _ := new(tables.Constitute).GetupConfigMap(consId)
		whereMap["academy"] = ci[tables.AcademyType].Name
		whereMap["profession"] = ci[tables.ProfessionType].Name
	} else {
		if academy != 0 {
			ci, _ := new(tables.Constitute).GetConstituteById(academy)
			whereMap["academy"] = ci.Name
		}
		if profession != 0 {
			ci, _ := new(tables.Constitute).GetConstituteById(profession)
			whereMap["profession"] = ci.Name
		}
	}

	if len(grade) != 0 && grade != "全部年级" && grade != "0" {
		whereMap["grade"] = grade
	}

	if len(query) != 0 { // 默认使用用户名查询
		query = "%" + query + "%" // 模糊查询
		if opt == 0 {
			d := variable.DB.MySQL.Where(whereMap).Where(where).Where("user_phone like ? or user_name like ? or sno like ?", query, query, query).Offset((page - 1) * pageSize).Limit(pageSize).Order("created_at desc").Preload("Career").Find(&ss).Offset(-1).Limit(-1).Count(&count)
			if d.RowsAffected == 0 {
				return out, count, "", nil
			}
		} else {
			d := variable.DB.MySQL.Where(whereMap).Where(where).Where("user_phone like ? or user_name like ? or sno like ?", query, query, query).Order("created_at desc").Preload("Career").Find(&ss)
			if d.RowsAffected == 0 {
				return out, 0, "", nil
			}
		}
	} else {
		if opt == 0 {
			d := variable.DB.MySQL.Where(whereMap).Where(where).Offset((page - 1) * pageSize).Limit(pageSize).Order("created_at desc").Preload("Career").Find(&ss).Offset(-1).Limit(-1).Count(&count)
			if d.RowsAffected == 0 {
				return out, count, "", nil
			}
		} else {
			d := variable.DB.MySQL.Where(whereMap).Where(where).Order("created_at desc").Preload("Career").Find(&ss)
			if d.RowsAffected == 0 {
				return out, 0, "", nil
			}
		}

	}
	var phontUri = variable.Config.UfsInfo.UfsUrl + variable.Config.UfsInfo.BucketPrefix
	for i := 0; i < len(ss); i++ {
		var trainLog model.QueryTrainLogResp
		trainLog.Id = ss[i].ID
		trainLog.Career = ss[i].CareerName
		trainLog.Academy = ss[i].Academy
		trainLog.Grade = ss[i].Grade
		trainLog.Name = ss[i].UserName
		trainLog.Phone = ss[i].UserPhone
		trainLog.Profession = ss[i].Profession
		trainLog.School = ss[i].School
		trainLog.TrainTime = ss[i].TrainAt.Format("2006-01-02 15:04:05")
		trainLog.ReportUrl = phontUri + ss[i].Url
		trainLog.ReportType = ss[i].Career.ReportType
		if ss[i].Career.ReportType == "web" {
			trainLog.ReportUrl = fmt.Sprintf(
				"https://growup.aminer.cn/%s/web-report?reportId=%d&careerId=%d",
				variable.Env, ss[i].ID, ss[i].CareerID,
			)
		}
		trainLog.Score = int((ss[i].TotalScore))
		trainLog.FinishTime = ss[i].FinishAt.Format("2006-01-02 15:04:05")
		trainLog.Status = ss[i].Status
		trainLog.Duration = fmt.Sprintf("%d分%d秒", ss[i].Duration/60, ss[i].Duration%60)
		trainLog.Education = ss[i].Education
		trainLog.Type = tables.UseTypeMap[ss[i].Type]
		trainLog.Sno = ss[i].Sno
		trainLog.ReportIsSync = ss[i].IsSync
		u := new(tables.User)
		variable.DB.MySQL.Select("IsSync").First(u, ss[i].UserID)
		if !u.IsSync {
			trainLog.ReportIsSync = false
		}
		agent := new(tables.Agent)
		agentSubquery := variable.DB.MySQL.Model(&tables.User{}).Select("agent_id").Where("id=?", ss[i].UserID)
		if err := variable.DB.MySQL.Select("IsSync").Where("id in (?)", agentSubquery).First(agent); err != nil {
			trainLog.AgentIsSync = true
		}
		trainLog.AgentIsSync = agent.IsSync
		out = append(out, trainLog)
	}
	if opt == 1 {
		dir, _ := os.Getwd()
		fileName := tools.Md5DataString(time.Now().String()) + ".xlsx"
		localPath := dir + "/logs/" + fileName
		if _, err := tools.SaveExcle(localPath, "sheet1", common.TrainLogDetailHeader, out); err != nil {
			log.Logger.InfoF(ctx, "文件保存失败"+fileName)
			// 记录日志
			go func() {
				defer tools.RecoverGoroutine()
				new(tables.OptionLog).InsertOptionLog(ctx, int64(len(out)), err)
			}()
			return out, count, "", fmt.Errorf("文件导出失败，请重试")
		} else {
			filePath := common.ExportFilePath + fileName
			sdk.FilePut(localPath, variable.Config.UfsInfo.BucketPrefix+filePath, sdk.XlsxMetaType)
			os.Remove(fileName)
			// 记录日志
			go func() {
				defer tools.RecoverGoroutine()
				new(tables.OptionLog).InsertOptionLog(ctx, int64(len(out)), err)
			}()
			return out, count, variable.Config.UfsInfo.UfsUrl + variable.Config.UfsInfo.BucketPrefix + filePath, nil
		}
	}
	return out, count, "", nil

}

func QueryTrainLogDetail(ctx *gin.Context, queryReq model.QueryTrainLogDetailReq) (out model.QueryTrainLogDetailResp, err error) {
	sid := queryReq.SessionId
	if sid == 0 {
		return out, fmt.Errorf("session_id错误~")
	}
	rq, _ := new(tables.RealQues).GetRealQuestionBySessionId(sid)
	var dialogue []model.Dialogue
	for _, v := range rq {
		var ansAnalysisTag []string
		err2 := json.Unmarshal([]byte(v.AnsAnalysisTag), &ansAnalysisTag)
		if err2 != nil {
			ansAnalysisTag = make([]string, 0)
		}

		dialogue = append(
			dialogue,
			model.Dialogue{
				Id:             v.ID,
				QuestionId:     v.QuestionID,
				Question:       v.QuestionText,
				Answer:         v.AnswerText,
				QuestionType:   int(v.QuestionType),
				AudioUrl:       v.Audio,
				SpeakTime:      v.SpeakTime,
				AnsAnalysis:    v.Question.AnsAnalysis,
				BelongToId:     *v.BelongToID,
				CurrentTag:     v.CurrentTag,
				AnsAnalysisTag: ansAnalysisTag,
			})
	}
	out.SessionId = sid
	out.Dialogue = dialogue
	return out, nil
}

// 面试记录 只有超级管理员可以获取到数据
func GetTrailList(ctx *gin.Context, gr model.GetStudentRequest) (count int64, out []model.StudentResp, err error) {
	// 获取当前用户的用户名
	uid, exists := ctx.Get("uid")
	if !exists {
		return 0, out, fmt.Errorf("操作失败~")
	}
	us, _ := tables.GetAgentInfoByUid(uid.(uint))
	var queryTrainLogList []model.QueryTrainLogListResp
	var query = gr.Query
	qlen := len(query)
	// 拼接where条件
	var whereStr = "url != ''"
	var page = gr.Page
	var pageSize = gr.PageSize
	var trainSort = gr.TrainSort
	var schoolId = gr.School
	var academyId = gr.Academy
	var professionId = gr.Profession
	var grade = gr.Grade
	var education = gr.Education
	var startTime = gr.StartTime
	var endTime = gr.EndTime

	if schoolId != 0 {
		if schoolId == 1 {
			whereStr = fmt.Sprintf("%s and school = '%s'", whereStr, "")
		} else {
			ci, _ := new(tables.Constitute).GetConstituteById(schoolId)
			if ci.Name == "游客" {
				whereStr = fmt.Sprintf("%s and school = '%s'", whereStr, "")
			} else {
				whereStr = fmt.Sprintf("%s and school = '%s'", whereStr, ci.Name)
			}
		}

	} else {
		if us.Level == tables.RolesLevel2 { // 确认管理员权限
			whereStr = fmt.Sprintf("%s and school = '%s'", whereStr, us.School)
		}
	}

	if academyId != 0 {
		ci, _ := new(tables.Constitute).GetConstituteById(academyId)
		whereStr = fmt.Sprintf("%s and academy = '%s'", whereStr, ci.Name)
	} else {
		if us.Level == tables.RolesLevel3 { // 确认管理员权限
			whereStr = fmt.Sprintf("%s and academy = '%s'", whereStr, us.Academy)
		}
	}
	if professionId != 0 {
		ci, _ := new(tables.Constitute).GetConstituteById(professionId)
		whereStr = fmt.Sprintf("%s and profession = '%s'", whereStr, ci.Name)
	} else {
		if us.Level == tables.RolesLevel4 { // 确认管理员权限
			whereStr = fmt.Sprintf("%s and profession = '%s'", whereStr, us.Profession)
		}
	}
	if len(grade) != 0 && grade != "0" {
		whereStr = fmt.Sprintf("%s and grade = '%s'", whereStr, grade)
	}
	if len(education) != 0 && education != "0" {
		whereStr = fmt.Sprintf("%s and education = '%s'", whereStr, education)
	}
	if startTime != nil && endTime != nil {
		whereStr = fmt.Sprintf("%s and  train_at >= '%s' and train_at <= '%s'", whereStr, startTime, endTime)
	}
	var selectInfo = "id, user_id, user_name, sno, user_phone, school, academy, profession, education, grade, count(user_id) as train_count"
	var dbQuery = variable.DB.MySQL.Model(&tables.Session{}).Select(selectInfo).Where(whereStr)
	if qlen != 0 {
		query = "%" + query + "%"
		dbQuery = dbQuery.Where("user_name like ? or user_phone like ? or sno like ?", query, query, query).Limit(pageSize).Offset((page - 1) * pageSize).Group("user_id")
	}
	// 查询所有数据
	dbQuery = dbQuery.Limit(pageSize).Offset((page - 1) * pageSize).Group("user_id")
	if trainSort == "desc" {
		dbQuery = dbQuery.Order("train_count desc")
	} else if trainSort == "asc" {
		dbQuery = dbQuery.Order("train_count asc")
	} else {
		dbQuery = dbQuery.Order("created_at desc")
	}
	d := dbQuery.Find(&queryTrainLogList)
	if d.Error != nil {
		return 0, out, fmt.Errorf("查询失败~")
	}
	d2 := dbQuery.Select("count(1) as train_count").Limit(-1).Offset(-1).Order(-1).Count(&count)
	if d2.Error != nil {
		return 0, out, fmt.Errorf("查询失败~")
	}

	// 整理返回数据
	for i := 0; i < len(queryTrainLogList); i++ {
		var mr model.StudentResp
		mr.Id = queryTrainLogList[i].UserId
		mr.Name = queryTrainLogList[i].UserName
		mr.Phone = queryTrainLogList[i].Phone
		mr.School = queryTrainLogList[i].School
		mr.Academy = queryTrainLogList[i].Academy
		mr.Profession = queryTrainLogList[i].Profession
		mr.Grade = queryTrainLogList[i].Grade
		mr.Academy = queryTrainLogList[i].Academy
		mr.Profession = queryTrainLogList[i].Profession
		mr.TrainCount = queryTrainLogList[i].TrainCount
		mr.Education = queryTrainLogList[i].Education
		mr.Sno = queryTrainLogList[i].Sno
		out = append(out, mr)
	}
	return count, out, nil
}

func DeleteTrainLog(ctx *gin.Context, ids []int) error {
	// 根据用户查询所有的用户id
	var sessions []tables.Session
	if d := variable.DB.MySQL.Where("id in (?)", ids).Find(&sessions); d.Error != nil {
		return fmt.Errorf("删除失败")
	}

	var userIdMap map[uint]uint = make(map[uint]uint, 0)
	for _, v := range sessions {
		if v.UserID == 0 {
			continue
		}
		userIdMap[v.UserID] = 0
	}
	for k := range userIdMap {
		var count int64
		if d := variable.DB.MySQL.Model(&tables.Session{}).Where("user_id = ? and status = 1", k).Count(&count); d.Error != nil {
			continue
		}
		variable.DB.MySQL.Model(&tables.User{}).Where("id = ?", k).Updates(map[string]interface{}{"train_count": count})
	}

	d := variable.DB.MySQL.Delete(&tables.Session{}, ids)
	if d.Error != nil {
		return fmt.Errorf("删除失败")
	}

	// 记录日志
	go func() {
		defer tools.RecoverGoroutine()
		new(tables.OptionLog).InsertOptionLog(ctx, d.RowsAffected, d.Error)
	}()

	return nil
}

// 根据用户id获取用户面试记录
func QueryTrainLogByUserId(ctx *gin.Context, uid int) (out []model.QueryTrainLogResp, err error) {
	ss, err := new(tables.Session).FindReportsByUID(uid)
	if err != nil {
		return out, err
	}
	if len(ss) == 0 {
		return out, err
	}
	var phontUri = variable.Config.UfsInfo.UfsUrl + variable.Config.UfsInfo.BucketPrefix
	for i := 0; i < len(ss); i++ {
		var trainLog model.QueryTrainLogResp
		trainLog.Id = ss[i].ID
		trainLog.Career = ss[i].CareerName
		trainLog.Academy = ss[i].Academy
		trainLog.Grade = ss[i].Grade
		trainLog.Name = ss[i].UserName
		trainLog.Phone = ss[i].UserPhone
		trainLog.Profession = ss[i].Profession
		trainLog.School = ss[i].School
		trainLog.TrainTime = ss[i].TrainAt.Format("2006-01-02 15:04:05")
		trainLog.ReportUrl = phontUri + ss[i].Url
		trainLog.ReportType = ss[i].Career.ReportType
		trainLog.Score = int((ss[i].TotalScore))
		trainLog.FinishTime = ss[i].FinishAt.Format("2006-01-02 15:04:05")
		trainLog.Status = ss[i].Status
		trainLog.Duration = fmt.Sprintf("%d分%d秒", ss[i].Duration/60, ss[i].Duration%60)
		trainLog.Education = ss[i].Education
		trainLog.Type = tables.UseTypeMap[ss[i].Type]
		trainLog.Sno = ss[i].Sno
		trainLog.ReportIsSync = ss[i].IsSync
		out = append(out, trainLog)
	}
	return out, nil
}
